/*
 * Copyright (c) 2020 - ~, HIT_HERO Team
 *
 * UARTCOM MODULE SOUCE FILE
 * Used in RT-Thread Operate System
 *
 * Change Logs:
 * Date           Author       Notes                Mail
 * 2020-08-25     WangXi       first version        WangXi_chn@foxmail.com
 * 2020-09-06     WangXi       second version       WangXi_chn@foxmail.com
 */
#include "Module_UartCom.h"

static void     Module_UartComInit(MODULE_UARTCOM *module);
static void     Module_UartComSend(MODULE_UARTCOM *module,rt_uint8_t packetID,rt_int32_t param);
static void     Module_UartComFeed(MODULE_UARTCOM *module,rt_uint8_t* packetID,rt_int32_t* param);
static rt_err_t Module_UartComHandle(rt_device_t dev, rt_size_t size);

static void     UartComEncode(MODULE_UARTCOM *module,rt_uint8_t packetID,rt_int32_t param);
static void     UartComDecode(MODULE_UARTCOM *module,rt_uint8_t* packetID,rt_int32_t* param);

static struct rt_semaphore uartCom_sem;

static void		Module_UartComJC24BConfig(MODULE_UARTCOM *module);

/* Global Method */
rt_err_t Module_UartCom_Config(MODULE_UARTCOM *module)
{
    if( module->Method_Init     ==NULL &&
        module->Method_Handle   ==NULL &&
        module->Method_Send     ==NULL &&
        module->Method_Feed     ==NULL
                
    ){  
        /* Link the Method */
        module->Method_Init         = Module_UartComInit;
        module->Method_Handle       = Module_UartComHandle;
        module->Method_Send         = Module_UartComSend;
        module->Method_Feed         = Module_UartComFeed;
        
    }
    else{
        rt_kprintf("Warning: Module uart Communication is Configed twice\n");
        return RT_ERROR;
    }

    /* Device Init */
    module->Method_Init(module);

    return RT_EOK;
}

static void Module_UartComInit(MODULE_UARTCOM *module)
{
    module->Value_uart_dev = rt_device_find(module->Property_UartDevName);
    if (!module->Value_uart_dev)
    {
        rt_kprintf("find %s failed!\t\n", module->Value_uart_dev);
        return;
    }
    
    rt_sem_init(&uartCom_sem, "uartCom_sem", 0, RT_IPC_FLAG_FIFO);
    
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  /* 初始化配置参数 */
	
    /* step2：修改串口配置参数 */
	if(module->Property_BaudRate == 9600)
	{
		config.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
	}
	else if(module->Property_BaudRate == 115200)
	{
		config.baud_rate = BAUD_RATE_115200;       //修改波特率为 115200
	}
    else
	{
		rt_kprintf("warning: Uartcom's baudrate %d set failed, will be default value 115200\t\n",module->Property_BaudRate);
	}
	
    config.data_bits = DATA_BITS_8;           //数据位 8
    config.stop_bits = STOP_BITS_1;           //停止位 1
    config.bufsz     = 128;                   //修改缓冲区 buff size 为 128
    config.parity    = PARITY_NONE;           //无奇偶校验位
    
    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(module->Value_uart_dev, RT_DEVICE_CTRL_CONFIG, &config);  
    rt_device_open(module->Value_uart_dev, RT_DEVICE_FLAG_DMA_RX);
    rt_device_set_rx_indicate(module->Value_uart_dev, module->Method_Handle);
	
	if(module->Property_Device == JC24B)
	{
		Module_UartComJC24BConfig(module);
	}
    
}

static void Module_UartComSend(MODULE_UARTCOM *module,rt_uint8_t packetID,rt_int32_t param)
{	
	UartComEncode(module,packetID,param);
    
    rt_device_write(    module->Value_uart_dev, 0, 
                        &(module->Value_sendData), 
                        sizeof(module->Value_sendData));
}

static void Module_UartComFeed(MODULE_UARTCOM *module,rt_uint8_t* packetID,rt_int32_t* param)
{
    rt_uint8_t ch;
    rt_uint8_t i = 0;

    while (1)
    {   
        while (rt_device_read(module->Value_uart_dev, -1, &ch, 1) == 0)
        {
            rt_sem_control(&uartCom_sem, RT_IPC_CMD_RESET, RT_NULL);
            rt_sem_take(&uartCom_sem, RT_WAITING_FOREVER);
        }
		
        if((rt_uint8_t)ch == 0xAA)
        {
			/* get the frame end flag and start encode the frame */
			UartComDecode(module,packetID,param);
			
            i = 0;
            continue;
        }
        i = (i >= UARTCOM_FRAME_LENGTH-1) ? UARTCOM_FRAME_LENGTH-1 : i;
        module->Value_feedData[i++] = ch;
    }   
}

static rt_err_t Module_UartComHandle(rt_device_t dev, rt_size_t size)
{   
    rt_sem_release(&uartCom_sem);

    return RT_EOK;
}

static void UartComEncode(MODULE_UARTCOM *module,rt_uint8_t packetID,rt_int32_t param)
{
    module->Value_sendData[0] = 0xA5;
    module->Value_sendData[1] = 0x5A;
	module->Value_sendData[2] = module->Value_AimID;
	module->Value_sendData[3] = module->Property_MyID;
	module->Value_sendData[4] = packetID;
	module->Value_sendData[5] = (rt_uint8_t)((param&0xFF000000)>>24);
	module->Value_sendData[6] = (rt_uint8_t)((param&0x00FF0000)>>16);
	module->Value_sendData[7] = (rt_uint8_t)((param&0x0000FF00)>>8);
	module->Value_sendData[8] = (rt_uint8_t)((param&0x000000FF));
	module->Value_sendData[9] = (rt_uint8_t)((module->Value_sendData[2])+
								(module->Value_sendData[3])+(module->Value_sendData[4])+
								(module->Value_sendData[5])+(module->Value_sendData[6])+
								(module->Value_sendData[7])+(module->Value_sendData[8]));
	module->Value_sendData[10] = 0xAA;       
}

static void UartComDecode(MODULE_UARTCOM *module,rt_uint8_t* packetID,rt_int32_t* param)
{
    if(	(rt_uint8_t)(module->Value_feedData[0])==	0xA5 					&&
		(rt_uint8_t)(module->Value_feedData[1])==	0x5A 					&&
		(rt_uint8_t)(module->Value_feedData[2])==	module->Property_MyID 	&&
		(rt_uint8_t)((module->Value_feedData[2])+
		(module->Value_feedData[3])+(module->Value_feedData[4])+
		(module->Value_feedData[5])+(module->Value_feedData[6])+
		(module->Value_feedData[7])+(module->Value_feedData[8]))
		==(module->Value_feedData[9]))
    {
		//Split the data
		module->Value_GetID = module->Value_feedData[3];
		
		rt_int32_t Date = ((module->Value_feedData[5])<<24) + ((module->Value_feedData[6])<<16)
						+((module->Value_feedData[7])<<8) + ((module->Value_feedData[8]));	
		
		*packetID = module->Value_feedData[4];
		param[*packetID] = Date;
	}
    else
    {
        return;
    }
}

static void	Module_UartComJC24BConfig(MODULE_UARTCOM *module)
{
	char Config_data[18];
	
	rt_pin_mode(module->Property_JC24BsetPin, PIN_MODE_OUTPUT);
	rt_pin_write(module->Property_JC24BsetPin, PIN_LOW);
	
	//0	   1    2   3    4   5    6    7      8    9        10    11     12   13     14   15    16    17
	//AA   5A	00  00   00  10   00   00     00   04       00	  1F	 00	  01     00	  12	00	  06
	//0xaa 0x5a 模块ID   组网ID   0x00 RF功率 0x00 波特率   0x00  RF信道 0x00 速率   0x00 0x12  0x00  和校验
	rt_thread_mdelay(1);

	Config_data[0] = 0xAA;
	Config_data[1] = 0x5A;
	Config_data[2] = 0x00;
	Config_data[3] = module->Property_MyID;
	Config_data[4] = 0x00;
	Config_data[5] = module->Property_NetID;
	Config_data[6] = 0x00;
	Config_data[7] = 0x00;
	Config_data[8] = 0x00;
	Config_data[9] = 0x04;
	Config_data[10] = 0x00;
	Config_data[11] = 0x1F;
	Config_data[12] = 0x00;
	Config_data[13] = 0x01;
	Config_data[14] = 0x00;
	Config_data[15] = 0x12;
	Config_data[16] = 0x00;
	Config_data[17] = 0x00;
	for(int i = 0;i<17;i++)
		Config_data[17] += Config_data[i];

	rt_device_write(	module->Value_uart_dev, 0, 
						Config_data, sizeof(Config_data));
						
	rt_thread_mdelay(1);
				
	rt_pin_write(module->Property_JC24BsetPin, PIN_HIGH);
}

/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
